Imports System.ComponentModel
Imports System.Web.UI
Imports OliverHine.Controls

Namespace OliverHine.Weather

    <DefaultProperty("ID"), ToolboxData("<{0}:Weather runat=server></{0}:Weather>")> _
    Public Class Weather
        Inherits Control
        Implements IPostBackEventHandler

        Private IsDesignMode As Boolean = False
        Private IsTraceActive As Boolean = True

#Region " Properties "

        Private _text As String
        <Bindable(True), Category("Appearance"), DefaultValue("")> Property [Text]() As String
            Get
                Return _text
            End Get

            Set(ByVal Value As String)
                _text = Value
            End Set
        End Property

        Private _location As String
        Public Property WeatherLocation() As String
            Get
                Return GetViewState("location", "USNY1434")
            End Get
            Set(ByVal Value As String)
                SetViewState("location", Value)
            End Set
        End Property

        Private _locale As Integer
        <Bindable(True), Category("Weather Settings"), DefaultValue(5)> Public Property WeatherLanguage() As String
            Get
                Return GetViewState("lang", "en-US") '"de-AT")
            End Get
            Set(ByVal Value As String)
                SetViewState("lang", Value)
            End Set
        End Property

        Private _length As Integer
        <Bindable(True), Category("Weather Settings"), DefaultValue(5)> Public Property WeatherLength() As Integer
            Get
                Return GetViewState("length", 5)
            End Get
            Set(ByVal Value As Integer)
                SetViewState("length", Value)
            End Set
        End Property

        Private _unit As String
        <Bindable(True), Category("Weather Settings"), DefaultValue(Common.Enums.Unit.Fahrenheit)> Public Property WeatherUnit() As Common.Enums.Unit
            Get
                Return _unit
            End Get
            Set(ByVal Value As Common.Enums.Unit)
                _unit = Value
            End Set
        End Property

        Private _style As String
        <Bindable(True), Category("Weather Settings"), DefaultValue(Common.Enums.Style.Today)> Public Property WeatherStyle() As Common.Enums.Style
            Get
                Return GetViewState("style", Common.Enums.Style.Today)
            End Get
            Set(ByVal Value As Common.Enums.Style)
                SetViewState("style", Value)
            End Set
        End Property

        'Private _details As Boolean
        <Bindable(True), Category("Weather Settings"), DefaultValue(True)> Public Property WeatherTodayDetails() As Boolean
            Get
                Return GetViewState("details", "True")
            End Get
            Set(ByVal Value As Boolean)
                SetViewState("details", Value)
            End Set
        End Property

        'Private _details As Boolean
        <Bindable(True), Category("Weather Settings"), DefaultValue("64x64")> Public Property IconSizeLarge() As String
            Get
                Return GetViewState("l:icon", "64x64")
            End Get
            Set(ByVal Value As String)
                SetViewState("l:icon", Value)
            End Set
        End Property

        <Bindable(True), Category("Weather Settings"), DefaultValue("64x64")> Public Property IconSizeSmall() As String
            Get
                Return GetViewState("s:icon", "64x64")
            End Get
            Set(ByVal Value As String)
                SetViewState("s:icon", Value)
            End Set
        End Property

        <Bindable(True), Category("Weather Settings"), DefaultValue(True)> Public Property Title() As Common.Enums.Title
            Get
                Return GetViewState("title", Common.Enums.Title.Closest)
            End Get
            Set(ByVal Value As Common.Enums.Title)
                SetViewState("title", Value)
            End Set
        End Property

        <Bindable(True), Category("Weather Settings"), DefaultValue(Common.Enums.HyperLinkMode.Postback)> Public Property HyperLinkMode() As Common.Enums.HyperLinkMode
            Get
                Return GetViewState("linkmode", Common.Enums.HyperLinkMode.Postback)
            End Get
            Set(ByVal Value As Common.Enums.HyperLinkMode)
                SetViewState("linkmode", Value)
            End Set
        End Property

        <Bindable(True), Category("Weather Settings"), DefaultValue(False)> Public Property Timestamp() As Boolean
            Get
                Return GetViewState("time", "False")
            End Get
            Set(ByVal Value As Boolean)
                SetViewState("time", Value)
            End Set
        End Property
        <Bindable(True), Category("Weather Settings"), DefaultValue("")> Public Property UniqueIdentifier() As String
            Get
                Return GetViewState("uid", Me.ID)
            End Get
            Set(ByVal Value As String)
                SetViewState("uid", Value)
            End Set
        End Property
        <Bindable(True), Category("Network Proxy Settings"), DefaultValue("")> Public Property ProxyServer() As String
            Get
                Return GetViewState("ps", String.Empty)
            End Get
            Set(ByVal Value As String)
                SetViewState("ps", Value)
            End Set
        End Property
        <Bindable(True), Category("Network Proxy Settings"), DefaultValue("")> Public Property ProxyPort() As Integer
            Get
                Return GetViewState("pp", -1)
            End Get
            Set(ByVal Value As Integer)
                SetViewState("pp", Value)
            End Set
        End Property
        <Bindable(True), Category("Network Proxy Settings"), DefaultValue("")> Public Property ProxyUsername() As String
            Get
                Return GetViewState("pu", String.Empty)
            End Get
            Set(ByVal Value As String)
                SetViewState("pu", Value)
            End Set
        End Property
        <Bindable(True), Category("Network Proxy Settings"), DefaultValue("")> Public Property ProxyPassword() As String
            Get
                Return GetViewState("pw", String.Empty)
            End Get
            Set(ByVal Value As String)
                SetViewState("pw", Value)
            End Set
        End Property

#End Region

#Region " Functions "
        Public Sub SetValue(ByVal Key As String, ByVal Value As String)
            If context.Request.Browser.Cookies = True Then
                'If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Warn("SetCookie: " & Key & " - " & Value)

                SetCookie(Key, Value)
            Else
                'If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Warn("SetViewState: " & Key & " - " & Value)

                SetViewState(Key, Value)
            End If
        End Sub
        Public Function GetValue(ByVal Key As String, ByVal DefaultValue As String) As String
            If context.Request.Browser.Cookies = True Then
                Dim Value As String = GetCookie(Key, DefaultValue)

                'If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Warn("GetCookie: " & Key & " - " & DefaultValue & " - " & Value)

                Return Value
            Else
                Dim Value As String = GetViewState(Key, DefaultValue)

                'If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Warn("GetViewState: " & Key & " - " & DefaultValue & " - " & Value)

                Return Value
            End If
        End Function


        Private Sub SetCookie(ByVal Key As String, ByVal Value As String)
            Dim sCacheKey As String = String.Format("{0}:{1}", Me.ID, Key)
            If context.Request.Browser.Cookies = True Then

                If Not context.Request.Cookies(sCacheKey) Is Nothing Then
                    context.Response.Cookies.Remove(sCacheKey)

                    context.Response.Cookies(sCacheKey).Value = Value
                Else
                    context.Response.Cookies(sCacheKey).Value = Value
                End If

            End If
        End Sub
        Private Function GetCookie(ByVal Key As String, ByVal DefaultValue As String) As String
            Dim sCacheKey As String = String.Format("{0}:{1}", Me.ID, Key)
            If context.Request.Browser.Cookies = True Then
                If Not context.Request.Cookies(sCacheKey) Is Nothing Then
                    Return context.Request.Cookies(sCacheKey).Value
                Else
                    Return DefaultValue
                End If
            End If
        End Function


        Private Sub SetViewState(ByVal Key As String, ByVal Value As String)
            Key = Me.ID & ":" & Key 'Instance-Specific StateBag Key
            If ViewState.Item(Key) Is Nothing Then
                ViewState.Add(Key, Value)
            Else
                ViewState.Item(Key) = Value
            End If
        End Sub
        Private Function GetViewState(ByVal Key As String, ByVal DefaultValue As String) As String
            Key = Me.ID & ":" & Key 'Instance-Specific StateBag Key

            If ViewState.Item(Key) Is Nothing Then
                Return DefaultValue
            Else
                Return ViewState.Item(Key).ToString()
            End If
        End Function
        Private Function GetWeatherString(ByVal Language As String, ByVal ProxyServer As String, ByVal ProxyPort As Integer, ByVal ProxyUsername As String, ByVal ProxyPassword As String) As String
            If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Warn("Language: " & Language)

            Dim weatherHtml As New System.IO.StringWriter

            Dim t As New Xml.Xsl.XslTransform
            Dim XsltArgumentList As Xml.Xsl.XsltArgumentList = TransformArguments()


            Dim doc As Xml.XmlDocument = Common.Functions.GetWeatherDocument(WeatherLocation, WeatherLength, WeatherUnit, Language, ProxyServer, ProxyPort, ProxyUsername, ProxyPassword)

            t.Load(CurrentStylesheet)
            t.Transform(doc, XsltArgumentList, weatherHtml, Nothing)

            Context.Cache.Insert(Me.UniqueIdentifier, weatherHtml.ToString.Replace("<?xml version=""1.0"" encoding=""utf-16""?>", String.Empty), Nothing, Now.AddMinutes(15), TimeSpan.Zero)

            Return weatherHtml.ToString.Replace("<?xml version=""1.0"" encoding=""utf-16""?>", String.Empty)
        End Function

        Private Function GetWeatherString(ByVal Language As String) As String
            Return GetWeatherString(Language, String.Empty, Nothing, String.Empty, String.Empty)
        End Function

        Private Function TransformArguments() As Xml.Xsl.XsltArgumentList
            TransformArguments = New Xml.Xsl.XsltArgumentList
            'If Not Settings("DetailedToday") Is Nothing Then bDetailedToday = CType(Settings("DetailedToday").ToString, Boolean)

            TransformArguments.AddParam("imgroot", "", ResolveUrl("images"))
            TransformArguments.AddParam("showdetails", "", WeatherTodayDetails)
            TransformArguments.AddParam("and", "", Helpers.Localization.GetString("xsl.And", WeatherLanguage))
            TransformArguments.AddParam("at", "", Helpers.Localization.GetString("xsl.At", WeatherLanguage))
            TransformArguments.AddParam("daylight", "", Helpers.Localization.GetString("xsl.Daylight", WeatherLanguage))

            Select Case Me.Title
                Case Common.Enums.Title.Actual
                    TransformArguments.AddParam("location", "", "obst")
                Case Common.Enums.Title.Closest
                    TransformArguments.AddParam("location", "", "dnam")
                Case Common.Enums.Title.Hide
                    TransformArguments.AddParam("location", "", "hide")
            End Select

            TransformArguments.AddParam("feelslike", "", Helpers.Localization.GetString("xsl.FeelsLike", WeatherLanguage))
            TransformArguments.AddParam("uv", "", Helpers.Localization.GetString("xsl.UV", WeatherLanguage))
            TransformArguments.AddParam("dewpoint", "", Helpers.Localization.GetString("xsl.DewPoint", WeatherLanguage))
            TransformArguments.AddParam("humidity", "", Helpers.Localization.GetString("xsl.Humidity", WeatherLanguage))
            TransformArguments.AddParam("visibility", "", Helpers.Localization.GetString("xsl.Visibility", WeatherLanguage))
            TransformArguments.AddParam("pressure", "", Helpers.Localization.GetString("xsl.Pressure", WeatherLanguage))
            TransformArguments.AddParam("wind", "", Helpers.Localization.GetString("xsl.Wind", WeatherLanguage))
            TransformArguments.AddParam("extended", "", Helpers.Localization.GetString("xsl.Extended", WeatherLanguage))

            TransformArguments.AddParam("iconlarge", "", IconSizeLarge)
            TransformArguments.AddParam("iconsmall", "", IconSizeSmall)
            TransformArguments.AddParam("timestamp", "", Timestamp)

        End Function

        Private Function CurrentStylesheet() As String
            If Me.HyperLinkMode = Common.Enums.HyperLinkMode.QueryString Then
                If Not context.Request.QueryString("weather") Is Nothing Then
                    'key is specified, load stylesheet based on query value!
                    'TODO, Loop through QueryValue and check for exact match!
                    If context.Request.QueryString("weather").IndexOf(Me.UniqueIdentifier) = -1 Then
                        'Me.WeatherStyle = Common.Enums.Style.Today
                        'Return Context.Server.MapPath(ResolveUrl("xslt\onlyToday.xsl"))
                        Select Case WeatherStyle
                            Case Common.Enums.Style.Extended, Common.Enums.Style.OnlyExtended
                                Return Context.Server.MapPath(ResolveUrl("xslt\onlyExtended.xsl"))

                            Case Common.Enums.Style.TodayWithExtended
                                Return Context.Server.MapPath(ResolveUrl("xslt\withExtended.xsl"))

                            Case Common.Enums.Style.Today, Common.Enums.Style.OnlyToday
                                Return Context.Server.MapPath(ResolveUrl("xslt\onlyToday.xsl"))
                            Case Else
                                Me.WeatherStyle = Common.Enums.Style.Today
                                Return Context.Server.MapPath(ResolveUrl("xslt\onlyToday.xsl"))
                        End Select

                    Else
                        Me.WeatherStyle = Common.Enums.Style.Extended
                        Return Context.Server.MapPath(ResolveUrl("xslt\onlyExtended.xsl"))
                    End If
                Else
                    Select Case WeatherStyle
                        Case Common.Enums.Style.Extended, Common.Enums.Style.OnlyExtended
                            Return Context.Server.MapPath(ResolveUrl("xslt\onlyExtended.xsl"))

                        Case Common.Enums.Style.TodayWithExtended
                            Return Context.Server.MapPath(ResolveUrl("xslt\withExtended.xsl"))

                        Case Common.Enums.Style.Today, Common.Enums.Style.OnlyToday
                            Return Context.Server.MapPath(ResolveUrl("xslt\onlyToday.xsl"))
                    End Select
                End If


            ElseIf Me.HyperLinkMode = Common.Enums.HyperLinkMode.Postback Then
                If OliverHine.Controls.Helpers.Common.Null.IsNull(WeatherStyle) = False Then
                    Select Case WeatherStyle
                        Case Common.Enums.Style.Extended, Common.Enums.Style.OnlyExtended
                            Return Context.Server.MapPath(ResolveUrl("xslt\onlyExtended.xsl"))

                        Case Common.Enums.Style.TodayWithExtended
                            Return Context.Server.MapPath(ResolveUrl("xslt\withExtended.xsl"))

                        Case Common.Enums.Style.Today, Common.Enums.Style.OnlyToday
                            Return Context.Server.MapPath(ResolveUrl("xslt\onlyToday.xsl"))
                    End Select
                Else
                    If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Warn("CurrentStylesheet: No Weather Style!!!")
                    Return Context.Server.MapPath(ResolveUrl("xslt\withExtended.xsl"))
                End If
            End If
        End Function
#End Region

#Region " Overriding Methods "
        Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
            MyBase.OnInit(e)

            Me.IsDesignMode = (System.Web.HttpContext.Current Is Nothing)
            If IsDesignMode = False Then Me.IsTraceActive = System.Web.HttpContext.Current.Trace.IsEnabled

            'Register the JavaScript for PNGfix
            Page.RegisterClientScriptBlock("oliverhine", "<!--[ Weather Control created by Oliver Hine - 2009 - oliverhine.com ]-->")
            Page.RegisterClientScriptBlock("pngfix", String.Format("<!--[if lt IE 7.]><script defer type=""text/javascript"" src=""{0}""></script><![endif]-->", ResolveUrl("pngfix.js")))
        End Sub

        Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
            Try

                RenderTheWeather(writer)

            Catch ex As Helpers.Exceptions.MissingFiles
                If WeatherLanguage.ToLower = "en-us" Then
                    'OH NO!!!
                    writer.Write(String.Format("{0}<hr>{1}<hr>{2}", ex.Message, ex.InnerException, ex.ToString))
                Else
                    WeatherLanguage = "en-US"
                    RenderTheWeather(writer)
                End If


            Catch ex As System.IO.DirectoryNotFoundException
                Throw New Helpers.Exceptions.MissingFiles("xsl template directory seems to be missing!")
            End Try
        End Sub

#End Region

        Private Sub RenderTheWeather(ByVal writer As System.Web.UI.HtmlTextWriter)
            'render the weather control
            writer.Write(GetWeatherString(Me.WeatherLanguage, Me.ProxyServer, Me.ProxyPort, Me.ProxyUsername, Me.ProxyPassword))

            If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Write(Me.UniqueIdentifier & " " & WeatherStyle)

            'create, and set the current Button Text
            Dim ButtonText As String = String.Empty

            Select Case Me.WeatherStyle
                Case Common.Enums.Style.Extended
                    ButtonText = Helpers.Localization.GetString("Switch.Back.Text", WeatherLanguage)
                Case Common.Enums.Style.Today
                    ButtonText = Helpers.Localization.GetString("Switch.Extended.Text", WeatherLanguage)
            End Select

            'format, and create the LinkButton, in it's selected mode
            Select Case Me.HyperLinkMode
                Case Common.Enums.HyperLinkMode.Postback

                    If ButtonText.Length > 0 Then writer.Write(String.Format("<br/><a class=""WeatherButton"" href=""javascript:{0}"">{1}</a>", Page.GetPostBackEventReference(Me, "switch"), ButtonText))

                Case Common.Enums.HyperLinkMode.QueryString
                    If ButtonText.Length > 0 Then writer.Write(String.Format("<br/><a class=""WeatherButton"" href=""{0}"">{1}</a>", Common.Functions.BuildQuerystringUrl(Context.Request, Me.UniqueIdentifier), ButtonText))

                Case Common.Enums.HyperLinkMode.Ajax


            End Select

            writer.Write("<br/><br/>")
        End Sub


        Private Sub Switch_Click(ByVal Sender As Object, ByVal E As EventArgs)
            If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Write("Start: Switch_Click()")

            Dim objWeather As Object = FindControl("weather")
            If Not objWeather Is Nothing Then
                Dim objSwitch As Object = FindControl("switch")
                If Not objSwitch Is Nothing Then
                    Dim lbSwitch As System.Web.UI.WebControls.LinkButton = DirectCast(objSwitch, System.Web.UI.WebControls.LinkButton)
                    WeatherStyle = lbSwitch.CommandName

                    Select Case lbSwitch.CommandName
                        Case "e"
                            lbSwitch.CommandName = "t"
                            lbSwitch.Text = Helpers.Localization.GetString("Switch.Back.Text", WeatherLanguage)
                            RaiseEvent LoadedExtended()

                        Case "t"
                            lbSwitch.CommandName = "e"
                            lbSwitch.Text = Helpers.Localization.GetString("Switch.Extended.Text", WeatherLanguage)
                            RaiseEvent LoadedToday()

                    End Select

                    DirectCast(objWeather, LiteralControl).Text = GetWeatherString(Me.WeatherLanguage)

                End If
            End If
        End Sub

        Public Sub RaisePostBackEvent(ByVal eventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
            If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Write("Start: RaisePostBackEvent()")

            If eventArgument = "switch" Then

                If IsTraceActive = True Then System.Web.HttpContext.Current.Trace.Warn("args=switch")

                Select Case Me.WeatherStyle
                    Case Common.Enums.Style.Today
                        Me.WeatherStyle = Common.Enums.Style.Extended
                    Case Common.Enums.Style.Extended
                        Me.WeatherStyle = Common.Enums.Style.Today
                End Select

            End If

        End Sub

        Public Event LoadedExtended()
        Public Event LoadedToday()



    End Class

End Namespace